/*
 * clsUDP
 * khoi dong listener, and phat dong 1 su kien moi khi bat duoc du lieu tu port
 * gui du lieu thong qua giao thuc udp
 *
 */


using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Threading;
using Microsoft.Win32;


namespace SmallDHCPServer_C
{
   class clsUDP

    {
        #region "Class Variables"
            private Int32 PortToListenTo, PortToSendTo = 0;
            private string rcvCardIP;
            public bool IsListening;
            // ham goi function send hay receive
            public UdpState s;
        #endregion

        #region "Class Events"
            public delegate void DataRcvdEventHandler(byte[] DData, IPEndPoint RIpEndPoint);
            public event DataRcvdEventHandler DataRcvd;
            public delegate void ErrEventHandler(string Msg);
        #endregion

            //class constructors
        public clsUDP()
        {
            IsListening = false;
        }
        //thong qua cong de khoi dong viec lang nghe hay goi message
        public clsUDP(Int32 PortToListenTo,Int32 PortToSendTo, string rcvCardIP) 
        {
            try
            {
                IsListening = false;
                this.PortToListenTo = PortToListenTo;
                this.PortToSendTo = PortToSendTo;
                this.rcvCardIP = rcvCardIP;
                StartListener();
            }
            catch(Exception ex) 
            {
               Console.WriteLine (ex.Message);
               
            }
        }

        private string ClassName
        {
            get {return "clsUDP";
            }
        }

        //gui data la mot byte stream toi socket
       // duoc thay doi de thuc hien nhu mot ham trieu goi
        public void SendData(byte[] Data)
        {

            try
            {
                //ham gui send message BeginSend(du lieu, length, host nhan, port gui, ham gui dong bo, lop se dai dien cho mot lan goi)
                s.u.BeginSend(Data, Data.Length, "255.255.255.255", PortToSendTo, new AsyncCallback(OnDataSent), s);
                //s.u.Send(Data, Data.Length, "255.255.255.255", PortToSendTo);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        // ham call back, duoc goi khi may client duoc ket noi
        public void OnDataSent(IAsyncResult asyn)
        {

            try
            {
                //lay du lieu
                UdpClient ii = (UdpClient)asyn;
                ii.EndSend(asyn); // dung ham send
            }
            catch (Exception ex)
            {
                if (IsListening == true)
                    Console.WriteLine(ex.Message);
            }
        }



       //ham lang nghe tat ca message service tu client
        private void IniListnerCallBack()
        {
            try
            {
               // start teh recieve call back method
                s.u.BeginReceive(new AsyncCallback(OnDataReceived), s);
            }
            catch (Exception ex)
            {
                if (IsListening == true)
                    Console.WriteLine(ex.Message);
            }
        }


        // ham call back, duoc goi khi client da connect toi server
       public void OnDataReceived(IAsyncResult asyn)
       {
           Byte[] receiveBytes;
           UdpClient u;
           IPEndPoint e;

           try
           {

               u = (UdpClient)((UdpState)(asyn.AsyncState)).u;
               e = (IPEndPoint)((UdpState)(asyn.AsyncState)).e;

               receiveBytes = u.EndReceive(asyn, ref e);

               DataRcvd(receiveBytes, e);
            }
           catch (Exception ex)
           {
               if (IsListening == true)
                   Console.WriteLine(ex.Message);
           }
           finally
           {
               u = null;
               e = null;
               receiveBytes = null;
               // recall the call back
               IniListnerCallBack();
           }
          
       }
           
       



        //ham start listener
        //neu listener dang khoi dong, se duoc tat va khoi dong lai
        // su dung 1 flag de danh dau rang listener dang hoat dong
        private void StartListener()
        {

            IPAddress ipAddress;
            IPEndPoint ipLocalEndPoint;


            try
            {

                IsListening = false;

                ipAddress = IPAddress.Parse(rcvCardIP);
                //lay ipendpoint
                ipLocalEndPoint = new IPEndPoint(ipAddress, PortToListenTo);
                // neu udpclient interface dang hoat dong thi tien hanh dong
                if (s.u != null) s.u.Close();
                s.u = null; s.e = null;

                //khoi tao lai udpclient
                             
                s = new UdpState();
                s.e = ipLocalEndPoint;
                s.u = new UdpClient(ipLocalEndPoint);
               
                IsListening = true; // start listen
                //lang nghe du lieu
                IniListnerCallBack();        
            }
            catch (Exception ex)
            {
                if (IsListening == true)
                    Console.WriteLine(ex.Message);
            }
            finally
            {
                 if (s.u == null) {
                    Thread.Sleep(1000);
                    StartListener(); }
                 else {
                    ipAddress = null;
                    ipLocalEndPoint = null; }
            }
        }



        //stop tien trinh listener
        public void StopListener()
        {
            try
            {
                IsListening = false;
                if (s.u != null) s.u.Close();
                s.u = null; s.e = null;

            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

        //huy tat ca cac resource
        ~clsUDP()
        {
            try
            {
                StopListener();
                if (s.u != null) s.u.Close();
                s.u = null; s.e = null;
                rcvCardIP = null;
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }

       //tao mot khoi tao cho ham call back udpclient va ipendpoint
       public struct UdpState
       {
           public IPEndPoint e; //dinh nghia endpoint
           public UdpClient u; //dinh nghia mot client
      }


    }
}
